﻿using Microsoft.SemanticKernel.Connectors.AI.OpenAI;
using Microsoft.SemanticKernel;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Microsoft.SemanticKernel.Connectors.Memory.Chroma;
using Microsoft.SemanticKernel.Plugins.Memory;
using Microsoft.DotNet.Interactive;
using Microsoft.SemanticKernel.Orchestration;

namespace SemanticKernelDemo {
    internal static class MemoryDemo {
        public static async Task<string> Run() {

            var kernelBuilder = new KernelBuilder();
            var (useAzureOpenAI, model, azureEndpoint, apiKey, orgId) = Settings.LoadFromFile();

            kernelBuilder.WithOpenAIChatCompletionService(model, apiKey, orgId);

            var kernel = kernelBuilder.Build();

            #region memory01
            var memoryBuilder = new MemoryBuilder();

            memoryBuilder.WithOpenAITextEmbeddingGenerationService("text-embedding-ada-002", apiKey);

            // var chromaMemoryStore = new ChromaMemoryStore("http://127.0.0.1:8000");
            // memoryBuilder.WithMemoryStore(chromaMemoryStore);
            memoryBuilder.WithMemoryStore(new VolatileMemoryStore());

            var memory = memoryBuilder.Build();

            const string MemoryCollectionName = "aboutMe";

            await memory.SaveInformationAsync(MemoryCollectionName, id: "info1", text: "My name is Andrea");
            await memory.SaveInformationAsync(MemoryCollectionName, id: "info3", text: "I currently live in Seattle and have been living there since 2005");
            await memory.SaveInformationAsync(MemoryCollectionName, id: "info5", text: "My family is from New York");

            #endregion

            #region memory02
            // TextMemoryPlugin provides the "recall" function
            kernel.ImportFunctions(new TextMemoryPlugin(memory));

            const string skPrompt = @"
            ChatBot can have a conversation with you about any topic.
            It can give explicit instructions or say 'I don't know' if it does not have an answer.

            Information about me, from previous conversations:
            - {{$fact1}} {{recall $fact1}}
            - {{$fact2}} {{recall $fact2}}
            - {{$fact3}} {{recall $fact3}}

            Chat:
            {{$history}}
            User: {{$userInput}}
            ChatBot: ";

            var chatFunction = kernel.CreateSemanticFunction(skPrompt, requestSettings: new OpenAIRequestSettings { MaxTokens = 200, Temperature = 0.8 });

            var context = kernel.CreateNewContext();

            context.Variables["fact1"] = "what is my name?";
            context.Variables["fact2"] = "where do I live?";
            context.Variables["fact3"] = "where is my family from?";

            context.Variables[TextMemoryPlugin.CollectionParam] = MemoryCollectionName;
            context.Variables[TextMemoryPlugin.RelevanceParam] = "0.6";

            var history = "";
            context.Variables["history"] = history;
            Func<string, Task> Chat = async (string input) => {
                // Save new message in the context variables
                context.Variables["userInput"] = input;

                // Process the user message and get an answer

                FunctionResult answer; 
                try {
                    Thread.Sleep(60000);
                    answer = await chatFunction.InvokeAsync(context);
                }
                catch (Exception ex) {
                    Thread.Sleep(60000);
                    answer = await chatFunction.InvokeAsync(context);
                }
                

                // Append the new interaction to the chat history
                history += $"\nUser: {input}\nChatBot: {answer.GetValue<string>()}\n";
                context.Variables["history"] = history;

                // Show the bot response
                Console.WriteLine("ChatBot: " + context);
            };
            await Chat("Hello, I think we've met before, remember? my name is...，answer me in chinese");
            await Chat("I want to plan a trip and visit my family. Do you know where that is? answer me in chinese");
            await Chat("Great! What are some fun things to do there? answer me in chinese");
            #endregion
            return "";
        }
    }
}
